﻿Imports System.Text
Imports System.Text.RegularExpressions
Imports System.Windows
Imports System.Windows.Input
Imports System.Windows.Media
Imports Microsoft.VisualStudio.Text
Imports Microsoft.VisualStudio.Text.Adornments
Imports Microsoft.VisualStudio.Text.Editor
Imports Microsoft.VisualStudio.Text.Formatting

Namespace Microsoft.VisualStudio.RegularExpression.LaunchingPoints
	Friend Class LaunchEditorMouseProcessor
		Inherits MouseProcessorBase
		Private ReadOnly Shared NewRegexStatementForCSharpOrVisualBasic As New Regex("[nN]ew\s+(Regex|System\.Text\.RegularExpressions\.Regex)\s*\(\s*", RegexOptions.Singleline Or RegexOptions.Compiled)

		Private view As IWpfTextView
		Private regexEditorService As RegexEditorService
		Private toolTipProviderFactory As IToolTipProviderFactory

		Friend Sub New(ByVal view As IWpfTextView, ByVal regexEditorService As RegexEditorService, ByVal toolTipProviderFactory As IToolTipProviderFactory)
			Me.view = view
			Me.regexEditorService = regexEditorService
			Me.toolTipProviderFactory = toolTipProviderFactory
			Me.IsToolTipShown = False
		End Sub

		Public Overrides Sub PreprocessMouseMove(ByVal e As MouseEventArgs)
			' Look for regex lines to show the tooltip/hand cursor
            For Each line In Me.view.TextViewLines
                Dim lineData = RegexLineData.CreateFromTextViewLine(Me.view, line)

                ' Check if the regex line contains a new Regex statement
                If IsValid(lineData) Then
                    ' Get the pattern parameter
                    Dim expression? = lineData.Expression

                    If expression.HasValue Then
                        ' Get the marker geometry of the pattern parameter
                        Dim expressionGeometry = view.TextViewLines.GetMarkerGeometry(expression.Value)
                        If expressionGeometry IsNot Nothing AndAlso expressionGeometry.Bounds.Contains(GetPointRelativeToView(e)) Then
                            e.Handled = True

                            If Not IsToolTipShown Then
                                IsToolTipShown = True
                                Dim toolTipProvider = Me.toolTipProviderFactory.GetToolTipProvider(Me.view)

                                ' Show the tooltip
                                toolTipProvider.ShowToolTip(expression.Value.Snapshot.CreateTrackingSpan(expression.Value.Span, SpanTrackingMode.EdgeExclusive), "Ctrl+Click to open the regex editor", PopupStyles.DismissOnMouseLeaveText)

                            End If
                            ' If the ctrl key is pressed change the cursor to hand
                            If Keyboard.IsKeyDown(Key.LeftCtrl) OrElse Keyboard.IsKeyDown(Key.RightCtrl) Then
                                e.MouseDevice.OverrideCursor = Cursors.Hand
                            End If
                            Return
                        End If
                    End If
                End If
            Next line

			IsToolTipShown = False
            e.MouseDevice.OverrideCursor = Nothing
		End Sub

		Private Function GetPointRelativeToView(ByVal e As MouseEventArgs) As Point
            Dim point = e.GetPosition(view.VisualElement)

			' Adjust the point by the viewport's location
			point.X += view.ViewportLeft
			point.Y += view.ViewportTop
			Return point
		End Function


		Public Overrides Sub PreprocessMouseLeftButtonUp(ByVal e As MouseButtonEventArgs)
			' Check if ctrl+click
			If Keyboard.IsKeyDown(Key.LeftCtrl) OrElse Keyboard.IsKeyDown(Key.RightCtrl) Then
				' Create a regex line data
                Dim lineData = RegexLineData.CreateFromCaretPosition(Me.view)

                ' Check if the line contains a new Regex statement
                If IsValid(lineData) Then
                    ' Get the regular expression parameter of the Regex ctor
                    Dim expression? = lineData.Expression

                    If expression.HasValue Then
                        ' Check if the click was made over the regular expression parameter.
                        If lineData.CaretPosition >= expression.Value.Start.Position AndAlso lineData.CaretPosition <= expression.Value.End.Position Then
                            Dim editorResult = Me.regexEditorService.ShowEditor(lineData.Expression.Value.GetText())
                            If editorResult.Result.HasValue AndAlso editorResult.Result.Value Then
                                Me.view.TextBuffer.Replace(lineData.Expression.Value.Span, editorResult.Pattern)
                            End If

                            e.Handled = True
                        End If
                    End If
                End If
			End If
		End Sub

		''' <summary>
		''' Returns true if the regex line contains a new Regex statement
		''' </summary>
		''' <param name="regexLineData"></param>
		''' <returns></returns>
		Private Function IsValid(ByVal regexLineData As RegexLineData) As Boolean
			Return NewRegexStatementForCSharpOrVisualBasic.IsMatch(regexLineData.Text)
		End Function

        Private Property IsToolTipShown As Boolean
	End Class
End Namespace
